package com.example.chaomi;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import android.content.Context;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;

/**
 * @author Giec:lijh
 *
 */
public class WifiUtils {
	
	private Context mContext;
	private  WifiManager mWifiManager;	
	
	public static final int SECURITY_OPEN = 0;
	public static final int SECURITY_WEP = 1;
	public static final int SECURITY_WPA = 2;	
	public static final int SECURITY_EAP = 3;
	public static final int SECURITY_UNKNOW = 4;	
	
	
	public WifiUtils(Context context) {
		mContext = context;
		mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
	}
	
	/**
	 * check isWifiConnected
	 * @return boolean,true means connected
	 */
	public boolean isWifiConnected() {
		WifiInfo wifiinfo = mWifiManager.getConnectionInfo();
		if(wifiinfo!=null){
			if(wifiinfo.getIpAddress()!=0)
				return true;
		}			
		return false;
	}	
	/**
	 * get CurrentConnectedSSID
	 * @return SSID or null 
	 */
	public String getCurrentConnectedSsid(){
		WifiInfo wifiinfo = mWifiManager.getConnectionInfo();
		if(wifiinfo!=null&&wifiinfo.getIpAddress()!=0)
			return wifiinfo.getSSID();
		else
			return null;
	}	
	/**
	 * open Wifi
	 * @return wifi State
	 */
	public int openWifi() {
		int state = mWifiManager.getWifiState();
		int wifiApState = mWifiManager.getWifiApState();
		if (state == WifiManager.WIFI_STATE_DISABLED
				|| state == WifiManager.WIFI_STATE_DISABLING
				|| state == WifiManager.WIFI_STATE_UNKNOWN) {
			mWifiManager.setWifiEnabled(true);
		}
		if(((wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) ||
                (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))){
			mWifiManager.setWifiApEnabled(null, false);
		}
		return mWifiManager.getWifiState();
	}

	public int getWifiState() {

		return mWifiManager.getWifiState();
	}

	public int closeWifi() {
		int state = mWifiManager.getWifiState();
		if (state == WifiManager.WIFI_STATE_ENABLED
				|| state == WifiManager.WIFI_STATE_ENABLING) {
			mWifiManager.setWifiEnabled(false);
		}
		return mWifiManager.getWifiState();
	}
	
	public int getWifiLevel(ScanResult result) {
		return result.level;
	}
	
	public int getSecurityType(ScanResult result) {
		if (result.capabilities == null) {
			return SECURITY_OPEN;
		}
		if (result.capabilities.contains("WPA")) {
			return SECURITY_WPA;
		} else if (result.capabilities.contains("WEP")) {
			return SECURITY_WEP;
		} else if (result.capabilities.contains("EAP")) {
			return SECURITY_EAP;
		} else {
			return SECURITY_UNKNOW;
		}
	}	
	
	/**
	 * getWifiAccessPointList
	 * @return List<ScanResult>
	 */
	public List<ScanResult> getWifiAccessPointList() {
		ArrayList<ScanResult> list = new ArrayList<ScanResult>();
		ArrayList<ScanResult> new_list = new ArrayList<ScanResult>();
		list.clear();
		new_list.clear();
		list = (ArrayList<ScanResult>)mWifiManager.getScanResults();
        
		for (ScanResult result : list) {
			if (result.SSID == null || result.SSID.length() == 0
					|| result.capabilities.contains("[IBSS]")) {
				continue;
			}
			new_list.add(result);
		}
		return removeDuplicateWithOrder(new_list);
	}
    /**
     * remove duplicate ssid
     * @param list
     * @return
     */
    private  ArrayList<ScanResult> removeDuplicateWithOrder(ArrayList<ScanResult> list){  
	 Set set=new HashSet();  
	 ArrayList<ScanResult> newList = new ArrayList<ScanResult>();  
        for (Iterator iter = list.iterator();iter.hasNext(); ) {  
            Object element = iter.next();  
            if (set.add(element)){
                newList.add((ScanResult)element);  
            }  
        }  
        return newList ;
	}
    
    
    public WifiConfiguration getSavedWifiConfig(String SSID,
			List<WifiConfiguration> existingConfigs) {
    	if(existingConfigs==null||existingConfigs.size()<=0)
    		return null;
		for (WifiConfiguration existingConfig : existingConfigs) {
			if (existingConfig.SSID.equals("\"" + SSID + "\"")) {
				return existingConfig;
			}
		}
		return null;
	}
    
	public void connect2AccessPoint(ScanResult scanResult, String password) {
		
		int securityType = getSecurityType(scanResult);
		List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
		WifiConfiguration config = getSavedWifiConfig(scanResult.SSID, configs);
		if (config == null) {
			config = new WifiConfiguration();
			config.SSID = "\"" + scanResult.SSID + "\"";
			config = getConfigBySecurityType(config, securityType,password);
			config.status = WifiConfiguration.Status.ENABLED;
			int netId = mWifiManager.addNetwork(config);
			mWifiManager.enableNetwork(netId, true);
            mWifiManager.saveConfiguration();
		} else {
			config.status = WifiConfiguration.Status.ENABLED;
			config = getConfigBySecurityType(config, securityType,password);
			mWifiManager.enableNetwork(config.networkId, true);
            mWifiManager.updateNetwork(config);
            mWifiManager.saveConfiguration();  // if ap is changed(such as password, securitytype),  need to save
		}

	}
	/**connect wifi
	 * @param config WifiConfiguration
	 */
	public void connect(WifiConfiguration config){
		mWifiManager.connect(config,wifiListener );
	}
	/**
	 * forget WifiConfiguration
	 * @param config
	 */
	public void forget(WifiConfiguration config){
		mWifiManager.forget(config.networkId,wifiListener);
	}
	/**
	 * forget scanResult by forget configuration of scanResult
	 * @param scanResult
	 */
	public void forget(ScanResult scanResult){
		forget(getSavedConfig(scanResult));
	}
	/**
	 * save WifiConfiguration and connect WifiConfiguration
	 * @param config
	 */
	public void save(WifiConfiguration config){
		mWifiManager.save(config, wifiListener);
		connect(config);
	}
	
	private WifiManager.ActionListener wifiListener = new WifiManager.ActionListener(){

		@Override
		public void onFailure(int arg0) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void onSuccess() {
			// TODO Auto-generated method stub
			
		}}; 
	private WifiConfiguration getConfigBySecurityType(WifiConfiguration config,
			int securityType,String password) {
			
		switch (securityType) {
		case SECURITY_OPEN:
			config.allowedKeyManagement.set(KeyMgmt.NONE);
			break;

		case SECURITY_WPA:
			config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
			config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
			config.preSharedKey = "\"" + password + "\"";
			break;   
		case SECURITY_WEP:
            config.allowedKeyManagement.set(KeyMgmt.NONE);
            config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
            config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
            int length =  password.length();
            // WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
            if ((length == 10 || length == 26 || length == 58) &&
                                password.matches("[0-9A-Fa-f]*")) {
                config.wepKeys[0] = password;
            } else {
                config.wepKeys[0] = '"' + password + '"';
            }
			break;
		case SECURITY_EAP:
			config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
			config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
			config.preSharedKey = "\"" + password + "\"";
			break;
        default :
            config.allowedKeyManagement.set(KeyMgmt.NONE);
			break;
		}

		return config;

	}
	public WifiConfiguration getSavedConfig(ScanResult msr){
		List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
		if(configs==null||configs.size()<=0)
			return null;
		for (WifiConfiguration config : configs) {

			if (config.SSID.equals("\"" + msr.SSID + "\"")) {
				return config;
			}
		}
		return null;
	}
	
	/**
	 * get wifi Config by ssid,security type,password provided, which is used for connection
	 * @param ssid
	 * @param security
	 * @param password
	 * @return WifiConfiguration
	 */
	public WifiConfiguration getConfig(String ssid,int security,String password) {
	        WifiConfiguration config = new WifiConfiguration();
	            config.SSID = "\"" + ssid + "\"";
	            // If the user adds a network manually, assume that it is hidden.
	            config.hiddenSSID = true;
	        switch (security) {
	            case SECURITY_OPEN:
	                config.allowedKeyManagement.set(KeyMgmt.NONE);
	                break;
	            case SECURITY_WEP:
	                config.allowedKeyManagement.set(KeyMgmt.NONE);
	                config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
	                config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
	                if (password.length() != 0) {
	                    int length = password.length();	                   
	                    // WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
	                    if ((length == 10 || length == 26 || length == 58) &&
	                            password.matches("[0-9A-Fa-f]*")) {
	                        config.wepKeys[0] = password;
	                    } else {
	                        config.wepKeys[0] = '"' + password + '"';
	                    }
	                }
	                break;
	            case SECURITY_WPA:
	                config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
	                if (password.length() != 0) {
	                    
	                    if (password.matches("[0-9A-Fa-f]{64}")) {
	                        config.preSharedKey = password;
	                    } else {
	                        config.preSharedKey = '"' + password + '"';
	                    }
	                }
	                break;
	            case SECURITY_EAP:
	            	config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
	    			config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
	    			config.preSharedKey = "\"" + password + "\"";
	                break;
	            default:
	                return null;
	        }
	        return config;
	    }
	public WifiConfiguration getWifiConfigurationForNetworkId(int networkId) {
        final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
        if (configs != null) {
            for (WifiConfiguration config : configs) {
                if (networkId == config.networkId &&
                        !(config.selfAdded && config.numAssociation == 0)) {
                    return config;
                }
            }
        }
        return null;
    }
}